﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MySQLStudio.ComponentModel;
using System.ComponentModel;

namespace MySQLStudio.BusinessLogic
{
    public class Table : BaseDatabaseObject, IColumnsContainer, ICloneable
    {
        private string m_engine;        
        private int? m_rows;        
        private DateTime? m_createTime;        
        private DateTime? m_updateTime;        
        private string m_collation;
        private ColumnCollection m_columns;
        private ColumnCollection m_deletedColumns;
                
        private string m_connectionString;
        private bool m_isPersisted;        

        public string Engine
        {
            get { return m_engine; }
            set { m_engine = value; }
        }

        public int? Rows
        {
            get { return m_rows; }
            set { m_rows = value; }
        }

        public DateTime? CreateTime
        {
            get { return m_createTime; }
            set { m_createTime = value; }
        }

        public DateTime? UpdateTime
        {
            get { return m_updateTime; }
            set { m_updateTime = value; }
        }

        public string Collation
        {
            get { return m_collation; }
            set { m_collation = value; }
        }

        public bool IsPersisted
        {
            get { return m_isPersisted; }
            internal set { m_isPersisted = value; }
        }

        #region IColumns Members

        public ColumnCollection Columns
        {
            get
            {
                if (m_columns == null)
                {
                    m_columns = TablesController.GetColumnsInTable(
                        m_connectionString,
                        m_schema, m_name);

                    m_columns.Container = this;
                    m_columns.ItemRemoved += new MySQLStudio.ComponentModel.ItemRemovedEventHandler(Columns_ItemRemoved);
                }

                return m_columns;
            }
        }

        #endregion

        internal ColumnCollection DeletedColumns
        {
            get
            {
                return m_deletedColumns;
            }            
        }

        private Table(string connectionString)
        {
            this.m_connectionString = connectionString;
            this.m_columns = new ColumnCollection(this);
            this.m_columns.ItemRemoved += new MySQLStudio.ComponentModel.ItemRemovedEventHandler(Columns_ItemRemoved);
            this.m_deletedColumns = new ColumnCollection();
        }

        void Columns_ItemRemoved(object sender, MySQLStudio.ComponentModel.ItemRemovedEventArgs e)
        {
            this.m_deletedColumns.Add((Column)e.DeletedItem);
        }        

        public Table(string connectionString, string schema, string name, string type, string engine, int? rows,
                     DateTime? createTime, DateTime? updateTime, string collation)
        {
            this.m_connectionString = connectionString;
            this.m_schema = schema;
            this.m_name = name;
            this.m_type = type;
            this.m_engine = engine;
            this.m_rows = rows;
            this.m_createTime = createTime;
            this.m_updateTime = updateTime;
            this.m_collation = collation;
            this.m_isPersisted = true;
            this.m_deletedColumns = new ColumnCollection();
        }

        public static Table CreateEmptyTable(Host host, Database database)
        {
            Table table = new Table(host.ConnectionString);

            table.Schema = database.Name;
            table.Name = string.Empty;
            table.Type = "TABLE";
            table.Engine = string.Empty;
            table.Rows = 0;
            table.CreateTime = null;
            table.UpdateTime = null;
            table.Collation = database.DefaultCollation;
            table.IsPersisted = false;

            return table;
        }

        public void Rename(Host host, Database database, string newName)
        {
            if (this.IsPersisted)
            {
                TablesController.Rename(host.ConnectionString, database.Name, this.Name, newName);
            }

            this.Name = newName;            
        }

        public void Delete(Host host, Database database)
        {
            if (this.IsPersisted)
            {
                TablesController.Delete(host.ConnectionString, database.Name, this.Name);
            }            
        }

        public void Create(Host host, Database database)
        {
            if (!this.IsPersisted)
            {
                TablesController.Create(host.ConnectionString, database.Name, this);
                this.Commit();
            }
        }

        public void Alter(Host host, Database database)
        {
            if (this.IsPersisted)
            {
                TablesController.Alter(host.ConnectionString, database.Name, this);
                this.Commit();
            }
        }

        private void Commit()
        {
            this.IsPersisted = true;
            this.Columns.Commit();
        }


        public string GetInsertStatement()
        {
            StringBuilder sbInsertStatement = new StringBuilder();

            ColumnCollection columns = this.Columns;

            if (columns != null)
            {
                sbInsertStatement.AppendFormat("insert into {0} \n", this.m_name);

                for (int i = 0; i < columns.Count; i++)
                {
                    if (i == 0)
                        sbInsertStatement.AppendFormat("\t({0}\n", columns[i].Name);
                    else if (i == this.m_columns.Count - 1)
                        sbInsertStatement.AppendFormat("\t,{0})\n", columns[i].Name);
                    else
                        sbInsertStatement.AppendFormat("\t,{0}\n", columns[i].Name);                    
                }

                sbInsertStatement.Append(" values \n");

                for (int i = 0; i < columns.Count; i++)
                {
                    if (i == 0)
                        sbInsertStatement.AppendFormat("\t(<{0}>\n", columns[i].Name);
                    else if (i == this.m_columns.Count - 1)
                        sbInsertStatement.AppendFormat("\t,<{0}>)\n", columns[i].Name);
                    else
                        sbInsertStatement.AppendFormat("\t,<{0}>\n", columns[i].Name);                                            
                }
            }

            return sbInsertStatement.ToString();
        }

        public string GetSelectStatement()
        {
            StringBuilder sbSelectStatement = new StringBuilder();

            ColumnCollection columns = this.Columns;

            if (columns != null)
            {
                sbSelectStatement.Append("select \n");

                for (int i = 0; i < columns.Count; i++)
                {
                    if (i == 0)
                        sbSelectStatement.AppendFormat("\t{0}\n", columns[i].Name);                    
                    else
                        sbSelectStatement.AppendFormat("\t,{0}\n", columns[i].Name);                
                }

                sbSelectStatement.AppendFormat(" from  {0} \n", this.m_name);                
            }

            return sbSelectStatement.ToString();
        }

        #region ICloneable Members

        public object Clone()
        {
            Table table = new Table(this.m_connectionString, this.m_schema, this.m_name, this.m_type, this.m_engine,
                this.m_rows, this.m_createTime, this.m_updateTime, this.m_collation);

            return table;
        }

        #endregion
    }
}
